package com.wqj.kyee.gps

import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.animation.PropertyValuesHolder
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.Handler
import android.os.IBinder
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import com.wqj.kyee.gps.nmea.NMEA
import com.wqj.kyee.gps.service.NMEAParserService
import com.wqj.kyee.gps.util.ToastUtil
import kotlinx.android.synthetic.main.activity_car_angle.*




class CarAngleActivity : AppCompatActivity(), View.OnClickListener, NMEAParserService.OnInfoUpdateListener{

    lateinit var mHandler: Handler
    //lateinit var mThread: BtReadThread
    val RIGHT: Int = 0
    val LEFT: Int = 1
    private var gestureDetector: GestureDetector? = null
    var plateTypes: Array<Int> = arrayOf(PLATE_SPEED, PLATE_SLOPE, PLATE_COMPASS, PLATE_ALTITUDE)
    // 当前在界面上显示的几个表盘
    var displayedPlates: ArrayList<Plate> = arrayListOf()
    var objectAnimatorPlate1: ObjectAnimator = ObjectAnimator()
    var objectAnimatorPlate2: ObjectAnimator = ObjectAnimator()
    var objectAnimatorPlate3: ObjectAnimator = ObjectAnimator()
    var plateAngleList: FloatArray = FloatArray(PLATE_COUNTS)
    // 代表表盘， 种类、view、相应的动画
    data class Plate(var view: View, var arrow: View, var plate_scale: View, var plate_bg: View, var animator: ObjectAnimator, var angle: Float, var type: Int, var digitalPanel : View)

    var TAG : String = "CarAngleActivity"

    var FLIP_DISTANCE : Int = 50

    var NEED_REFRESH_UI : Boolean = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_car_angle)

        mHandler = Handler()
        displayedPlates.add(Plate(plate1, arrow1, scale1, bg1, objectAnimatorPlate1, 0f, PLATE_SPEED, id_tv_digital_panelOne))
        displayedPlates.add(Plate(plate2, arrow2, scale2, bg2, objectAnimatorPlate2, 0f, PLATE_COMPASS,id_tv_digital_panelTwo))
        displayedPlates.add(Plate(plate3, arrow3, scale3, bg3, objectAnimatorPlate3, 0f, PLATE_SLOPE,id_tv_digital_panelThree))
       // mHandler = MyHandler(this)
       // mThread = BtReadThread(mHandler)
        gestureDetector = GestureDetector(this@CarAngleActivity, onGestureListener)
        arrow1.setOnTouchListener{ v, e -> gestureDetector!!.onTouchEvent(e)}
        arrow2.setOnTouchListener{ v, e -> gestureDetector!!.onTouchEvent(e)}
        arrow3.setOnTouchListener{ v, e -> gestureDetector!!.onTouchEvent(e)}

        id_tv_digital_panelThree.setPadding(0,50,0,0) //For pitch degree display

        plateAngleList[0] = 0f
        plateAngleList[1] = 0f
        plateAngleList[2] = 0f
        plateAngleList[3] = 0f

        id_fab_back_home.setOnClickListener(this)
    }

    override fun onClick(p0: View?) {
        when (p0?.id) {
            R.id.id_fab_back_home -> {
                finish()
            }
        }
    }


    override fun onStart() {
        super.onStart()
       // mThread.start()

        if (!isServcieBond) {
            val intent = Intent(this, NMEAParserService::class.java)
            isServcieBond = bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE)
        }
    }

    override fun onResume() {
        super.onResume()

        NEED_REFRESH_UI = true
    }

    override fun onPause() {
        super.onPause()

        NEED_REFRESH_UI = false
    }

    override fun onStop() {
        super.onStop()

        if (isServcieBond) {
            unbindService(mServiceConnection)
            isServcieBond = false
        }
    }

    override fun onDestroy() {
        super.onDestroy()

        Log.e(TAG, "onDestroy")
        if (mNMEAParserService != null)
            mNMEAParserService!!.setOnInfoUpdateListener(null)
    }

    override fun onRMCUpdate(position: NMEA.GPSPosition?) {
        var data: NMEA.GPSPosition = position as NMEA.GPSPosition

        if (NEED_REFRESH_UI) {
            mHandler.post({
                updatePlatesData(displayedPlates, data, DATA_TYPE_RMC)
            })
        }
    }

    override fun onGGAUpdate(position: NMEA.GPSPosition?) {
        var data: NMEA.GPSPosition = position as NMEA.GPSPosition

        if (NEED_REFRESH_UI) {
            mHandler.post({
                updatePlatesData(displayedPlates, data, DATA_TYPE_GGA)
            })
        }
    }

    override fun onAHRSUpdate(position: NMEA.GPSPosition?) {
        var data: NMEA.GPSPosition = position as NMEA.GPSPosition

        if (NEED_REFRESH_UI) {
            mHandler.post({
                updatePlatesData(displayedPlates, data, DATA_TYPE_AHRS)
            })
        }
    }

    override fun onGSVUpdate(svList: java.util.ArrayList<NMEA.SVInfo>?) {

    }

    private var isServcieBond = false
    private var mNMEAParserService: NMEAParserService? = null
    private val mServiceConnection = object : ServiceConnection {

        override fun onServiceConnected(componentName: ComponentName, service: IBinder) {
            Log.e(TAG, "onServiceConnected")
            mNMEAParserService = (service as NMEAParserService.LocalBinder).service

            if (mNMEAParserService != null) {
                mNMEAParserService!!.setOnInfoUpdateListener(this@CarAngleActivity)
            }
        }

        override fun onServiceDisconnected(componentName: ComponentName) {
            Log.e(TAG, "onServiceDisconnected")
            mNMEAParserService = null
        }
    }

    private fun isTouchPointInView(view : View, x : Int, y : Int): Boolean {
        if (view == null)
            return false;

        var location = IntArray(2)

        view.getLocationOnScreen(location)
        var left = location[0]
        var top = location[1]
        var right = left + view.measuredWidth
        var bottom = top + view.measuredHeight

        if (y >= top && y <= bottom && x >= left && x <= right)
            return true;

        return false;
    }

    private val onGestureListener = object : GestureDetector.SimpleOnGestureListener() {
        override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float,
                             velocityY: Float): Boolean {
            val x = e2.rawX - e1.rawX
            val y = e2.rawY - e1.rawY
            var plate: Plate? = null


            run breaking@ {
                displayedPlates.forEach {
//                    if (isInViewArea(it.view, e1.rawX, e1.rawY)) {
//                        plate = it
//                        return@breaking
//                    }
                    if (isTouchPointInView(it.view, e1.rawX.toInt(), e1.rawY.toInt())) {
                        plate = it
                        return@breaking
                    }
                }
            }



            if (plate == null) {
                Log.e(TAG, "plate is null")
                //return true
                //if (y < -10f) {
                //    id_ll_home.visibility = View.VISIBLE;
                //}
            } else {
                Log.e(TAG, "e1.rawX : " + e1.rawX + " ,e2.rawX:" + e2.rawX)
                if ((e1.rawX - e2.rawX) > FLIP_DISTANCE) {
                    doResult(plate!!, RIGHT)
                } else if ((e2.rawX - e1.rawX) > FLIP_DISTANCE) {
                    doResult(plate!!, LEFT)
                }
            }
            return true
        }
    }

    fun doResult(plate: Plate, action: Int) {
        var newType : Int = -1
        var animationDuration = 200L
        when (action) {
            RIGHT -> {
                Log.e(TAG, "swipe right->left")
                var transX = PropertyValuesHolder.ofFloat("translationX", 0f, 1000f)
                var anim1 = ObjectAnimator.ofPropertyValuesHolder(plate.view, transX).setDuration(100)
                transX = PropertyValuesHolder.ofFloat("translationX", -1000f, 0f)
                var anim2 = ObjectAnimator.ofPropertyValuesHolder(plate.view, transX).setDuration(100)
                val animSet = AnimatorSet()
                animSet.play(anim2).after(anim1)
                animSet.setDuration(animationDuration)
                animSet.start()
                newType = if ((plate.type-1)<0) plateTypes.size-1 else plate.type-1
                //updatePlateView(plate)
                Log.e(TAG, "plate type: " + plate.type)
            }

            LEFT -> {
                Log.e(TAG, "swipe left->right")
                var transX = PropertyValuesHolder.ofFloat("translationX", 0f, -1000f)
                var anim1 = ObjectAnimator.ofPropertyValuesHolder(plate.view, transX).setDuration(100)
                transX = PropertyValuesHolder.ofFloat("translationX", 1000f, 0f)
                var anim2 = ObjectAnimator.ofPropertyValuesHolder(plate.view, transX).setDuration(100)
                val animSet = AnimatorSet()
                animSet.play(anim2).after(anim1)
                animSet.setDuration(animationDuration)
                animSet.start()
                newType = if ((plate.type+1)>=plateTypes.size) 0 else plate.type+1
                Log.e(TAG, "plate type: " + plate.type)
            }
        }
        Handler().postDelayed({
            updatePlateView(plate, newType)
        }, animationDuration / 2)
    }


    @Synchronized private fun updatePlateView(plate: Plate, newType : Int) {
        (plate.arrow as ImageView).rotation = 0f
        (plate.plate_bg as ImageView).rotation = 0f
        (plate.plate_scale as ImageView).rotation = 0f
        when (newType) {
            PLATE_SPEED -> {
                plate.type = newType

                (plate.arrow as ImageView).setImageResource(R.mipmap.plate_speed_arrow)
                (plate.plate_bg as ImageView).setImageResource(R.mipmap.plate_speed_bg)
                (plate.plate_scale as ImageView).setImageResource(R.mipmap.plate_speed_bg)
                (plate.arrow as ImageView).rotation = plateAngleList[PLATE_SPEED]

                (plate.digitalPanel as TextView).visibility = View.GONE
            }
            PLATE_ALTITUDE -> {
                plate.type = newType

                (plate.arrow as ImageView).setImageResource(R.mipmap.plate_altitude_bg)
                (plate.plate_bg as ImageView).setImageResource(R.mipmap.plate_altitude_bg)
                (plate.plate_scale as ImageView).setImageResource(R.mipmap.plate_altitude_bg)

                (plate.arrow as ImageView).rotation = 0f
                (plate.plate_bg as ImageView).rotation = 0f
                (plate.plate_scale as ImageView).rotation = 0f

                var tv = plate.digitalPanel as TextView
                tv.visibility = View.VISIBLE
                tv.setPadding(0, 0, 0, 0)
                tv.text = ""
            }
            PLATE_COMPASS -> {
                plate.type = newType

                (plate.arrow as ImageView).setImageResource(R.mipmap.plate_compass_arrow)
                (plate.plate_bg as ImageView).setImageResource(R.mipmap.plate_compass_bg)
                (plate.plate_scale as ImageView).setImageResource(R.mipmap.plate_compass_scale)
                (plate.plate_scale as ImageView).rotation = plateAngleList[PLATE_COMPASS]

                (plate.digitalPanel as TextView).visibility = View.GONE
            }
            PLATE_SLOPE -> {
                plate.type = newType

                (plate.arrow as ImageView).setImageResource(R.mipmap.plate_slope_arrow)
                (plate.plate_bg as ImageView).setImageResource(R.mipmap.plate_slope_bg)
                (plate.plate_scale as ImageView).setImageResource(R.mipmap.plate_slope_line)
                (plate.arrow as ImageView).rotation = plateAngleList[PLATE_SLOPE]

                var tv = plate.digitalPanel as TextView
                tv.visibility = View.VISIBLE
                tv.setPadding(0, 50, 0, 0)
                tv.text = ""
            }
            else -> {
                ToastUtil.show(this, "Plate 类型错误!")
            }
        }
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        return gestureDetector!!.onTouchEvent(event)
    }

   /*public class MyHandler(activity: CarAngleActivity) : Handler() {

        //对Activity的弱引用
        val mActivity: CarAngleActivity
        init {
            mActivity = activity
        }
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                BtDevicesActivity.GPS_BOARD_DATA -> {
                    var data: NMEA.GPSPosition = msg.obj as NMEA.GPSPosition
                    updatePlatesData(mActivity.displayedPlates, data)
                }
                else -> super.handleMessage(msg)
            }
        }
    }*/

    private fun updateDigitalPanel(digitalPanel: View, text : String) {
        (digitalPanel as TextView).text = text
    }


    private fun updatePlatesData(plates: ArrayList<Plate>, data: NMEA.GPSPosition, dataType : Int) {
        var speed = data.velocity * 3.6f  // To Km/h
        speed *= 1.2f    //1.2f = 360 / 300
        var degree_z = data.dir
        var degree_y = data.dir
        //var altitude = data.altitude
        var animator: ObjectAnimator
        var animationDuration: Long = 300
        synchronized(this) {
            plates.forEach {
                animator = it.animator

                if (dataType == DATA_TYPE_RMC) {
                    when (it.type) {
                        CarAngleActivity.PLATE_SPEED -> {
                            if (animator.isRunning) {
                                animator.cancel()
                            }
                            animator.target = it.arrow
                            animator.propertyName = "rotation"
                            animator.setDuration(animationDuration)
                            animator.setFloatValues(plateAngleList[PLATE_SPEED], speed)
                            animator.start()
                            plateAngleList[PLATE_SPEED] = speed
                        }
                        CarAngleActivity.PLATE_COMPASS -> {
                            if (animator.isRunning) {
                                animator.cancel()
                            }
                            animator.target = it.plate_scale
                            animator.propertyName = "rotation"
                            animator.setDuration(animationDuration)
                            animator.setFloatValues(plateAngleList[PLATE_COMPASS], degree_z)
                            animator.start()
                            plateAngleList[PLATE_COMPASS] = degree_z
                        }
                    }
                } else if (dataType == DATA_TYPE_GGA) {
                    when (it.type) {
                        CarAngleActivity.PLATE_ALTITUDE -> {
                            if (animator.isRunning) {
                                animator.cancel()
                            }
                            //animator.target = it.arrow
                            //animator.propertyName = "rotation"
                            //animator.setDuration(500)
                            //animator.setFloatValues(plateAngleList[PLATE_ALTITUDE], altitude)
                            //animator.start()
                            //plateAngleList[PLATE_ALTITUDE] = altitude
                            val altitude = Math.round(data.altitude)
                            //(it.digitalPanel as TextView).setText(altitude.toString())
                            //mHandler.post({
                            updateDigitalPanel(it.digitalPanel, altitude.toString())
                            //})

                        }
                    }
                } else if (dataType == DATA_TYPE_AHRS) {
                    when (it.type) {
                        CarAngleActivity.PLATE_SLOPE -> {
                            if (animator.isRunning) {
                                animator.cancel()
                            }
                            animator.target = it.arrow
                            animator.propertyName = "rotation"
                            animator.setDuration(animationDuration)
                            animator.setFloatValues(plateAngleList[PLATE_SLOPE], degree_y)
                            animator.start()
                            plateAngleList[PLATE_SLOPE] = degree_y

                            //(it.digitalPanel as TextView).setText(Math.round(data.dir).toString())

                            //mHandler.post({
                            updateDigitalPanel(it.digitalPanel, Math.round(data.dir).toString() + "°")  //alt + 176
                            //})
                        }
                    }
                }
            }
        }
    }


    companion object {
        val PLATE_SPEED: Int = 0
        val PLATE_SLOPE: Int = 1
        val PLATE_COMPASS: Int = 2
        val PLATE_ALTITUDE: Int = 3
        val PLATE_COUNTS: Int = 4

        val DATA_TYPE_RMC: Int = 1
        val DATA_TYPE_GGA: Int = 2
        val DATA_TYPE_AHRS : Int = 3
    }

}
